import { type } from 'os';
import { type Ref, type ComputedRef, type VNode } from 'vue';

export type Record = { [key: string]: any };

interface TABLE {}

export enum DEFAULT_MENU {
  COPY = 'COPY',
  PAETS = 'PAETS',
  UNDO = 'UNDO',
  REDO = 'REDO',
  COPY_DOWN = 'COPY_DOWN',
  ADD_STEP_DOWN = 'ADD_STEP_DOWN',
  INSERT_BEFORE_ROWS = 'INSERT_BEFORE_ROWS',
  INSERT_AFTER_ROWS = 'INSERT_AFTER_ROWS',
  INSERT_COPY_AFTER_ROWS = 'INSERT_COPY_AFTER_ROWS',
  DELETE_ROWS = 'DELETE_ROWS',
}

export interface FastKeyboard {
  Ctrl_C: 'Ctrl_C';
  Ctrl_V: 'Ctrl_V';
  Ctrl_Z: 'Ctrl_Z';
  Ctrl_Y: 'Ctrl_Y';
  Delete: 'Delete';
}

export interface Menu {
  key: DEFAULT_MENU;
  label?: string | Ref<string> | ComputedRef<string> | VNode;
  input?: boolean; // 是否启用input
  inputDefaultValue?: number, // 默认值
  inputPrecision?: number, // 精度
  inputProps?: Record; // input props
  hide?: ComputedRef<boolean | undefined> | boolean | ((menu: Menu, data: {
    rowindexs: number[];
    columns: Column[];
    records: Record[];
    source: Ref<Record>;
  }, table: TABLE) => boolean);
  validator?: ((menu: Menu, data: {
    rowindexs: number[];
    columns: Column[];
    records: Record[];
    source: Ref<Record>;
  }, table: TABLE) => Promise<string>);
  disabled?: ((menu: Menu, data: {
    rowindexs: number[];
    columns: Column[];
    records: Record[];
    source: Ref<Record>;
  }, table: TABLE) => boolean);
  handler?: (menu: Menu, data: {
    rowindexs: number[];
    columns: Column[];
    records: Record[];
    source: Ref<Record>;
  }, table: TABLE) => void;
  handlerBefore?: (menu: Menu, data: {
    rowindexs: number[];
    columns: Column[];
    records: Record[];
    source: Ref<Record>;
  }, table: TABLE) => Promise<void>;
  handlerAfter?: (menu: Menu) => void;
  vForm?: any,
  _disabled?: boolean
}

export interface SelectedState {
  startX?: number;
  startY?: number;
  endX?: number;
  endY?: number;
  selectedTh?: boolean;
  cells?: [number, number][] // 自由选择单元格 [[rowindex, colindex], ...], 选中表头时， 将为[-1, *]
  rows?: number[] // 自由选择行 [rowindex]
}
export interface EditState {
  editX?: number;
  editY?: number;
  status?: 'ready' | 'doing'; // ready准备编辑中，doing聚焦编辑中
}
export type FieldPath = string | string[];
export interface Column {
  title: string;
  dataIndex: FieldPath;
  key: ColumnKey,
  type: 'text' | 'select' | 'checkbox'; // 表格列单元格内容类型
  valueType?: 'string' | 'number' | 'boolean'; // 列的数据类型，在复制粘贴时，如果想不丢失数据类型，亲配置此项
  options?: { label: string; value: number | string }[];
  slotName?: string;
  width?: number;
  minWidth?: number;
  fixed?: boolean | 'left' | 'right';
  tooltip?: boolean; // 是否开启Tooltip
  autoTooltip?: boolean; // 是否开启自动判断显示Tooltip， 开启Tooltip时有效
  sortOrder?: boolean|'ascend'|'descend'; // 排序方式（受控），ascend | descend | false
  sorter?: boolean| ((type: false|'ascend'|'descend') => void); // 打开排序，可以自定义排序函数
  rules?: Rule[] | Rule
  customCopy?: (
    data: {
      value: any, 
      rowindex: number, 
      record: Record, 
      source: Ref<Record>
    },
    selected: {
      rowindexs: number[];
      columns: Column[];
      records: Record[];
      source: Ref<Record>;
    }
  ) => string; // 自定义复制，返回的字符串将被decode，传回customPaste回调的参数中
  customPaste?: (
    data: {
      value: any, 
      rowindex: number, 
      record: Record, 
      source: Ref<Record>
    },
    selected: {
      rowindexs: number[];
      columns: Column[];
      records: Record[];
      source: Ref<Record>;
    }
  ) => void;
}
export interface DataSource {
  [key: string]: any;
}

type RowKey = string;
type SelectedRowKeys = string[];
type DisableSelectedRowKeys = string[];
type ColumnKey = string;
export interface RowSelection {
  selectedRowKeys: SelectedRowKeys; // 指定选中项的 key 数组，需要和 onChange 进行配合
  disableSelectedRowKeys?: DisableSelectedRowKeys; // 指定禁止选择的key数组
  fixed?: boolean; //把选择框列固定在左边
  // type?: 'checkbox' | 'radio'; // 多选/单选，checkbox or radio
  onChange?: (selectedRowKeys: SelectedRowKeys, selectedRows: Record[]) => void; //选中项发生变化时的回调
  onSelect?: (record: Record, selected: boolean, selectedRows: Record[]) => void; //用户手动选择/取消选择某行的回调
  onSelectAll?: (selected: boolean, selectedRowKeys: SelectedRowKeys, selectedRows: Record[]) => void; // 用户手动选择/取消选择所有行的回调
}

export type CustomRow = (record: Record, index: number) => ({
  onClick?: (event: Event) => void,       // 点击行
  onDblclick?: (event: Event) => void,
  onContextmenu?: (event: Event) => void,
  onMouseenter?: (event: Event) => void,  // 鼠标移入行
  onMouseleave?: (event: Event) => void,
  // onSelect?: (selectedRows: Record[], rowindexs: number[]) => void, // 内部选择行
} & Record)

export interface Props {
  dataSource?: Ref<DataSource[]>;
  columns?: Ref<Column[]>;
  rowKey: RowKey;
  rowSelection: RowSelection;
  defaultRowData?: () => Record; // 行默认数据
  menus?: (Menu | string)[];
  wrapMenusClassName?: string // 菜单外层容器样式名
  keepLastRowEmpty?: boolean; // 保持最后一行空数据
  resizeCol?: boolean; // 手动调整列宽
  showRowIndex?: boolean; // 是否显示行号
  showRowDrag?: boolean; // 是否开启拖拽行功能
  showColDrag?: boolean; // 是否开启拖拽列功能
  stickyHead?: boolean | number; // 表头是否启用粘性
  stickyIndex?: boolean | number; // 行号是否启用粘性
  readonly?: boolean | RowKey[]; // 只读模式、或者指定行只读
  disabled?: boolean | RowKey[]; // 禁用编辑、或者指定行禁用编辑
  openVirtualScroll?: boolean; // 是否开启虚拟滚动
  oneDataHeight?: number; // 每一行的高度，在开启虚拟滚动时至关重要
  relateRowChosed?: boolean; // 是否启动关联表格选择行，开启时，表格内容的选择行将与行选择checkbox联动
  customRow?: CustomRow; // 行属性配置
  customEditer?: CustomEditer; // 编辑配置
  border?: boolean; // 显示边框
  messageConfig?: Object; // 国际化配置
  openUndo?: boolean; // 是否启用撤销、重做
  fastKeyboard?: FastKeyboard[] // 快捷键配置
  checkNoRepaeatRowKey?: boolean
}

export interface Options {
  table: Ref<Element | null | undefined>;
  columns: Ref<Column[]>;
  dataSource: Ref<DataSource[]>;
  props: Props;
  emits: any;
}
export interface ErrorsState {
  [key: RowKey]: {
    [key: ColumnKey]: any
  }
}
export interface Rule {
  field: FieldPath,
  trigger?: 'selected' | 'blur' | 'change' | 'submit', // 验证时机，默认submit
  len?: number,
  min?: number,
  max?: number,
  message?: string,
  pattern?: RegExp, // 自定义正则
  required?: boolean,
  precision?: number, // 数字精度
  validator?: ((
    data: {
      rule: Rule,
      value: unknown,
      record: Record,
      rowindex: number
    }, 
    validateFields: ((
      filedList?: FieldPath[], 
      rowindex?: number
    ) => Promise<unknown>) // 手动触发验证手柄
  ) => Promise<string>),
}

// 编辑相关事件
export interface CustomEditer {
  disabledSelectTh?: boolean // 是否禁止选择表头
  disabledSelectCell?: boolean // 是否禁止选择格
  disabledSelectRow?: boolean // 是否禁止选择行
  singleSelectRow?: boolean // 是否只能单选行
  singleSelectCell?: boolean // 是否只能单选格
  selectedRowKeys?: string[] // 指定选中行的 key 数组
  disabledOuterClickClearSelected?: boolean // 是否禁止表格区域外点击事件清除选区
  // 返回Promise.reject, 将阻止更改数据
  onEditBefore: (data: {
    rowindexs: number[];
    columns: Column[];
    records: Record[];
    source: Ref<Record>;
  }, table: TABLE) => Promise<any> | void
  onSelected: (data: {
    rowindexs: number[];
    columns: Column[];
    records: Record[];
    source: Ref<Record>;
  }, table: TABLE) => void
  onChange: (data: {newValue: any, oldValue: any, column: Column, record: Record}) => void
  onBlur: (data: {newValue: any, oldValue: any, column: Column, record: Record}) => void
  onFocus: (data: {value:any, column: Column, record: Record}) => void
  onClear: (data: {newValue: any, oldValue: any, column: Column, record: Record}[]) => void
  onRemove: () => void
  rules?: Rule[] | Rule
  scrollToFirstError: boolean // 是否自动滚动到首个验证不通过位置
}

// 导出方法
export interface Exporse{
  validate: () => Promise<unknown>
}

export const PROVIDE_READONLY = Symbol()
export const PROVIDE_EDIT_STATE = Symbol()